clear;
clc;
global h dataBuffer maxPoints s startTime stringBuffer; % 声明全局变量

% 初始化全局变量
dataBuffer = [];           % 用于存储解析后的数据
maxPoints = 100;           % 图形最多显示的点数
stringBuffer = "";         % 字符串缓冲区，用于拼接未完整接收到的数据

% 打开串口
port = "COM10";            % 替换为实际串口号
baudRate = 115200;         % 替换为实际波特率
s = serialport(port, baudRate);  % 打开串口

configureTerminator(s, "LF");  % 配置换行符（假设发送端以 \n 结束每行数据）
flush(s);                      % 清空串口缓冲区

% 创建实时绘图对象
figure;
h = animatedline('Color', 'b');  % 设置蓝色的动态线条
ax = gca;
ax.YLim = [-1.5, 1.5];           % 根据数据范围设置 Y 轴
ax.XLim = [0, 10];               % 初始设置 X 轴范围（最近 10 秒）
grid on;

% 初始化时间
startTime = posixtime(datetime('now'));  % 获取程序启动时刻的 POSIX 时间戳

% 设置更新控制
updateInterval = 0.05;          % 每 0.05 秒更新一次图形
lastUpdateTime = 0;             % 上次更新时间

% 提示信息
disp('接收数据中...');

% 主循环
while true
    try
        % 检查串口是否有可用数据
        if s.NumBytesAvailable > 0
            % 读取数据，按换行符分割
            newData = readline(s);  % 读取一行数据（以换行符为结束标志）

            % 尝试将字符串转换为浮点数
            data = str2double(newData);  % 转换为浮点数
            if ~isnan(data)  % 检查是否成功转换
                % 更新数据缓冲区
                dataBuffer = [dataBuffer; data]; 
                if length(dataBuffer) > maxPoints
                    dataBuffer = dataBuffer(end - maxPoints + 1:end);  % 保留最后 maxPoints 个数据
                end

                % 控制图形更新频率
                currentTime = posixtime(datetime('now')) - startTime;  % 当前时间
                if currentTime - lastUpdateTime > updateInterval
                    % 添加点到实时图形
                    addpoints(h, currentTime, data);
                    ax.XLim = [currentTime - 10, currentTime];  % 动态调整 X 轴范围
                    drawnow;  % 刷新图形
                    lastUpdateTime = currentTime;  % 更新最后的更新时间
                end
            else
                % 如果转换失败，可以选择打印错误信息
                disp(['接收到无效数据：', newData]);
            end
        end

        % 控制主循环频率
        pause(updateInterval);

    catch ME
        % 捕获并显示错误
        disp(['主循环中的错误: ', ME.message]);
        disp(ME.getReport());

        % 清理串口对象
        if exist('s', 'var') && isvalid(s)
            delete(s);
        end
        break;  % 跳出主循环
    end
end
